package com.big.security.service.impl;

import com.big.common.utils.UUIDGenerate;
import com.big.common.utils.UUIDGenerator;
import com.big.model.model.patient.PatientDsn;
import com.big.model.vo.patient.PatientVo;
import com.big.patient.PatientFeignClient;
import com.big.security.domain.ResultCode;
import com.big.security.domain.ResultJson;
import com.big.security.domain.auth.ResponseUserToken;
import com.big.security.domain.auth.Role;
import com.big.security.domain.auth.UserDetail;
import com.big.security.exception.CustomException;
import com.big.security.mapper.AuthMapper;
import com.big.security.service.AuthService;
import com.big.security.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * 认证服务实现
 */
@Service
public class AuthServiceImpl implements AuthService {
    //身份验证管理器
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService userDetailsService;
    private final JwtUtils jwtTokenUtil;
    //授权映射器
    private final AuthMapper authMapper;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * 服务
     */
    @Autowired
    PatientFeignClient patientFeignClient;

    @Autowired
    public AuthServiceImpl(AuthenticationManager authenticationManager, @Qualifier("CustomUserDetailsService") UserDetailsService userDetailsService, JwtUtils jwtTokenUtil, AuthMapper authMapper) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtTokenUtil = jwtTokenUtil;
        this.authMapper = authMapper;
    }

    /**
     *注册
     调用服务添加
     */
    @Override
    public UserDetail register(UserDetail userDetail) {
        final String username = userDetail.getUsername();
        System.out.println("返回值"+patientFeignClient.findInfoDns(username));
        if( patientFeignClient.findInfoDns(username) == null  ) {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            final String rawPassword = userDetail.getPassword();
//            946121803
            userDetail.setId(Long.valueOf("90"+UUIDGenerator.getUUID7()));
            userDetail.setPassword(encoder.encode(rawPassword));
            userDetail.setLastPasswordResetDate(new Date());
            System.out.println("userDetail:\t"+userDetail);
            PatientVo patientVo=new PatientVo();
            patientVo.setUserId(Long.valueOf("94"+UUIDGenerator.getUUID7()));
            patientVo.setPhone(username);
            patientVo.setPassword(userDetail.getPassword());
            patientVo.setName(userDetail.getUsername());
            patientVo.setAvatar("https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png");
            System.out.println("patientVo:\t"+patientVo);
            patientFeignClient.saves(patientVo);
            Long roleId = userDetail.getRole().getId();
            System.out.println("roleId:\t"+roleId);

            System.out.println("------------------------------开始角色------------------------------");
            Role role = authMapper.findRoleById(roleId);
            System.out.println("role:\t"+role);
            userDetail.setRole(role);
            authMapper.insertRole(patientVo.getUserId(), roleId);
        }else {
            throw new CustomException(ResultJson.failure(ResultCode.BAD_REQUEST, "用户已存在"));
        }
        return userDetail;
    }

    /**
     * 登录
     * @param username
     * @param password
     * @return
     */
    @Override
    public ResponseUserToken login(String username, String password) {
        System.out.println("username:"+username+"\t"+password);
        //用户验证
        final Authentication authentication = authenticate(username, password);
        System.out.println("Authorization:\t"+authentication);
        //存储认证信息
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //生成token
        final UserDetail userDetail = (UserDetail) authentication.getPrincipal();
        final String token = jwtTokenUtil.generateAccessToken(userDetail);
        //存储token
        jwtTokenUtil.putToken(username, token);
        return new ResponseUserToken(token, userDetail);

    }

    /**
     * 登出
     * @param token
     */
    @Override
    public void logout(String token) {
        token = token.substring(tokenHead.length());
        String userName = jwtTokenUtil.getUsernameFromToken(token);
        jwtTokenUtil.deleteToken(userName);
    }

    /**
     * 刷新
     * @param oldToken
     * @return
     */
    @Override
    public ResponseUserToken refresh(String oldToken) {
        String token = oldToken.substring(tokenHead.length());
        String username = jwtTokenUtil.getUsernameFromToken(token);
        UserDetail userDetail = (UserDetail) userDetailsService.loadUserByUsername(username);
        if (jwtTokenUtil.canTokenBeRefreshed(token, userDetail.getLastPasswordResetDate())){
            token =  jwtTokenUtil.refreshToken(token);
            return new ResponseUserToken(token, userDetail);
        }
        return null;
    }

    /**
     * 按令牌获取用户
     * @param token
     * @return
     */
    @Override
    public UserDetail getUserByToken(String token) {
        token = token.substring(tokenHead.length());
        return jwtTokenUtil.getUserFromToken(token);
    }

    /**
     * 认证
     */
    private Authentication authenticate(String username, String password) {
        System.out.println("authenticate方法:"+username+"\t"+password);
        try {
            //该方法会去调用userDetailsService.loadUserByUsername()去验证用户名和密码，如果正确，则存储该用户名密码到“security 的 context中”
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (DisabledException | BadCredentialsException e) {
            throw new CustomException(ResultJson.failure(ResultCode.LOGIN_ERROR, e.getMessage()));
        }
    }
}
